package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.uqbike.object.pojo.dto.OrderAnalysisQueryDTO;
import com.tbit.uqbike.object.pojo.vo.OrderAnalysisLineVo;
import com.tbit.uqbike.object.pojo.vo.OrderAnalysisVO;
import com.tbit.uqbike.object.pojo.vo.OrderFunnelVO;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.OrderAnalysisService;
import com.tbit.uqbike.webmanager.dao.stat.OrderAnalysisDao;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.Assert;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户订单分析
 *
 * @author <a href="mailto:liu.haoxiang@tbit.com.cn">BUGXiang</a>
 * @version 1.0
 * @since 2024-7-11
 */
@Service
public class OrderAnalysisServiceImpl implements OrderAnalysisService {


    @Resource
    private OrderAnalysisDao orderAnalysisDao;


    /**
     * 用户订单分析
     *
     * @param orderAnalysisQueryDTO 查询条件
     * @return 用户订单分析
     */
    @Override
    public PageResult<OrderAnalysisVO> queryOrderAnalysis(OrderAnalysisQueryDTO orderAnalysisQueryDTO) {
        Assert.notNulls("参数异常", orderAnalysisQueryDTO.getPage(), orderAnalysisQueryDTO.getSize(), orderAnalysisQueryDTO.getBrandId(), orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime());
        if (DateUtil.between(orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime(), DateUnit.DAY) > 31) {
            Assert.isTrue(false, "查询时间范围不能超过31天");
        }
        PageInfo<OrderAnalysisVO> pageInfo = PageHelper.startPage(orderAnalysisQueryDTO.getPage(), orderAnalysisQueryDTO.getSize()).doSelectPageInfo(() -> orderAnalysisDao.queryOrderAnalysis(orderAnalysisQueryDTO));
        return new PageResult<>(orderAnalysisQueryDTO.getPage(), orderAnalysisQueryDTO.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList());

    }

    /**
     * 导出用户订单分析
     *
     * @param orderAnalysisQueryDTO 查询条件
     * @return excel
     */
    @Override
    public Result<Object> exportOrderAnalysis(OrderAnalysisQueryDTO orderAnalysisQueryDTO) {
        //限制导出数量
        orderAnalysisQueryDTO.setPage(1);
        orderAnalysisQueryDTO.setSize(60000);
        List<OrderAnalysisVO> list = queryOrderAnalysis(orderAnalysisQueryDTO).getList();
        ExcelUtil<OrderAnalysisVO> excelUtil = new ExcelUtil<>(OrderAnalysisVO.class);
        String fileName = String.format("%s~%s_用户订单分析", DateUtil.formatDate(orderAnalysisQueryDTO.getStartTime()), DateUtil.formatDate(orderAnalysisQueryDTO.getEndTime()));
        JsonResult result = excelUtil.exportExcel(list, fileName);
        return Result.success(result.getData());
    }

    /**
     * 用户订单漏斗分析
     *
     * @param orderAnalysisQueryDTO 查询条件
     * @return result
     */
    @Override
    public Result<Object> orderAnalysisFunnel(OrderAnalysisQueryDTO orderAnalysisQueryDTO) {
        Assert.notNulls("参数异常", orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime());
        if(Objects.isNull(orderAnalysisQueryDTO.getAccountId()) && CollectionUtil.isEmpty(orderAnalysisQueryDTO.getAccountIds())){
            return Result.error("请选择区域");
        }
        if (DateUtil.between(orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime(), DateUnit.DAY) > 365) {
            Assert.isTrue(false, "查询时间范围不能超过一年");
        }
        OrderFunnelVO orderFunnelVO = new OrderFunnelVO();
        //获取这段时间的数据
        List<OrderAnalysisVO> orderAnalysisVOS = orderAnalysisDao.queryOrderAnalysis(orderAnalysisQueryDTO);
        if (CollectionUtil.isEmpty(orderAnalysisVOS)){
            return Result.success();
        }
        for (OrderAnalysisVO orderAnalysisVO : orderAnalysisVOS) {
            //总扫码次数
            orderFunnelVO.setScanCodeCount(NumberUtil.add(orderFunnelVO.getScanCodeCount(), orderAnalysisVO.getScanCodeCount()).intValue());
            //总开锁次数
            orderFunnelVO.setUnlockCount(NumberUtil.add(orderFunnelVO.getUnlockCount(), orderAnalysisVO.getUnlockCount()).intValue());
            //正常开锁次数
            orderFunnelVO.setNormalUnlockCount(NumberUtil.add(orderFunnelVO.getNormalUnlockCount(), orderAnalysisVO.getNormalUnlockCount()).intValue());
            //成功开锁次数
            orderFunnelVO.setSuccessUnlockCount(NumberUtil.add(orderFunnelVO.getSuccessUnlockCount(), orderAnalysisVO.getSuccessUnlockCount()).intValue());
            //有效订单数
            orderFunnelVO.setValidOrderCount(NumberUtil.add(orderFunnelVO.getValidOrderCount(), orderAnalysisVO.getValidOrderCount()).intValue());

            //低电开锁次数
            orderFunnelVO.setLowPowerUnlockCount(NumberUtil.add(orderFunnelVO.getLowPowerUnlockCount(), orderAnalysisVO.getLowPowerUnlockCount()).intValue());
            //故障开锁次数
            orderFunnelVO.setFaultUnlockCount(NumberUtil.add(orderFunnelVO.getFaultUnlockCount(), orderAnalysisVO.getFaultUnlockCount()).intValue());
            //超区开锁次数
            orderFunnelVO.setOutAreaUnlockCount(NumberUtil.add(orderFunnelVO.getOutAreaUnlockCount(), orderAnalysisVO.getOutAreaUnlockCount()).intValue());
            //其他异常开锁次数
            orderFunnelVO.setOtherUnlockCount(NumberUtil.add(orderFunnelVO.getOtherUnlockCount(), orderAnalysisVO.getOtherUnlockCount()).intValue());
        }
        //计算漏斗数据百分比
        orderFunnelVO.setScanCodeCountPercent("100%");
        //总开锁次数百分比 开锁总次数/扫码总次数
        orderFunnelVO.setUnlockCountPercent(NumberUtil.div(new BigDecimal(orderFunnelVO.getUnlockCount()), new BigDecimal(orderFunnelVO.getScanCodeCount()), 2).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).toString() + "%");
        //正常开锁次数百分比 正常开锁次数/扫码总次数
        orderFunnelVO.setNormalUnlockCountPercent(NumberUtil.div(new BigDecimal(orderFunnelVO.getNormalUnlockCount()), new BigDecimal(orderFunnelVO.getScanCodeCount()), 2).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).toString() + "%");
        //成功开锁次数百分比 成功开锁次数/扫码总次数
        orderFunnelVO.setSuccessUnlockCountPercent(NumberUtil.div(new BigDecimal(orderFunnelVO.getSuccessUnlockCount()), new BigDecimal(orderFunnelVO.getScanCodeCount()), 2).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).toString() + "%");
        //有效订单数百分比 有效订单数/扫码总次数
        orderFunnelVO.setValidOrderCountPercent(NumberUtil.div(new BigDecimal(orderFunnelVO.getValidOrderCount()), new BigDecimal(orderFunnelVO.getScanCodeCount()), 2).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP).toString() + "%");
        return Result.success(orderFunnelVO);
    }

    /**
     * 订单流失分析折线图
     * @param orderAnalysisQueryDTO 查询条件
     * @return result
     */
    @Override
    public Result<Object> orderAnalysisLine(OrderAnalysisQueryDTO orderAnalysisQueryDTO) {
        Assert.notNulls("参数异常", orderAnalysisQueryDTO.getAccountId(), orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime());
        if (DateUtil.between(orderAnalysisQueryDTO.getStartTime(), orderAnalysisQueryDTO.getEndTime(), DateUnit.DAY) > 365) {
            Assert.isTrue(false, "查询时间范围不能超过一年");
        }
        //获取这段时间的数据
        List<OrderAnalysisVO> orderAnalysisVOS = orderAnalysisDao.queryOrderAnalysis(orderAnalysisQueryDTO);

        // 使用Stream API将列表转换为Map
        Map<String, OrderAnalysisVO> dateMap = orderAnalysisVOS.stream()
                .collect(Collectors.toMap(OrderAnalysisVO::getAddTime, orderAnalysisVO -> orderAnalysisVO, (existingValue, newValue) -> existingValue));
        //获取开始时间到结束时间的日期集合
        String startDate = DateUtil.format(orderAnalysisQueryDTO.getStartTime(), "yyyy-MM-dd");
        String endDate = DateUtil.format(orderAnalysisQueryDTO.getEndTime(), "yyyy-MM-dd");
        List<String> allDatesBetween = getAllDatesBetween(DateUtil.parse(startDate, "yyyy-MM-dd"), DateUtil.parse(endDate, "yyyy-MM-dd"));

        List<OrderAnalysisLineVo> lineVoList = new ArrayList<>();

        for (String date : allDatesBetween) {
            OrderAnalysisLineVo orderAnalysisLineVo = new OrderAnalysisLineVo();
            orderAnalysisLineVo.setAddTime(date);
            if (dateMap.containsKey(date)) {
                //如果包含该日期，则获取该日期对应的数据
                OrderAnalysisVO orderAnalysisVO = dateMap.get(date);
                orderAnalysisLineVo.setLowPowerLossRate(Objects.isNull(orderAnalysisVO.getLowPowerLossRate()) ? "0%" : orderAnalysisVO.getLowPowerLossRate());
                orderAnalysisLineVo.setOutAreaLossRate(Objects.isNull(orderAnalysisVO.getOutAreaLossRate()) ? "0%" : orderAnalysisVO.getOutAreaLossRate());
                orderAnalysisLineVo.setFaultLossRate(Objects.isNull(orderAnalysisVO.getFaultLossRate()) ? "0%" : orderAnalysisVO.getFaultLossRate());
           }else {
                orderAnalysisLineVo.setLowPowerLossRate("0%");
                orderAnalysisLineVo.setOutAreaLossRate("0%");
                orderAnalysisLineVo.setFaultLossRate("0%");
            }
            lineVoList.add(orderAnalysisLineVo);
       }
        return Result.success(lineVoList);
    }

    /**
     * 获取开始日期和结束日期之间的所有天数
     */
    public static List<String> getAllDatesBetween(DateTime startDate, DateTime endDate) {
        List<String> dates = new ArrayList<>();
        DateTime current = startDate;
        while (!current.isAfter(endDate)) {
            dates.add(current.toString("yyyy-MM-dd"));
            current = current.offsetNew(DateField.DAY_OF_MONTH, 1); // 增加一天
        }

        return dates;
    }
}
